import threading
import time
import random

# 共享数据
shared_data = 0
# 信号量
mutex = threading.Semaphore(1)  # 保护read_count
wrt = threading.Semaphore(1)  # 读写互斥
read_count = 0  # 当前读者数量


# 读者优先 - 读者线程
def reader_priority(reader_id):
    global read_count, shared_data
    while True:
        # 进入区
        mutex.acquire()
        read_count += 1
        if read_count == 1:
            wrt.acquire()  # 第一个读者获取写锁
        mutex.release()

        # 临界区 - 读取数据
        print(f"读者{reader_id} 读取数据: {shared_data}")
        time.sleep(random.uniform(0.1, 0.5))

        # 退出区
        mutex.acquire()
        read_count -= 1
        if read_count == 0:
            wrt.release()  # 最后一个读者释放写锁
        mutex.release()

        time.sleep(random.uniform(0.5, 1.5))


# 读者优先 - 写者线程
def writer_priority(writer_id):
    global shared_data
    while True:
        # 进入区
        wrt.acquire()

        # 临界区 - 写入数据
        shared_data = random.randint(1, 100)
        print(f"写者{writer_id} 写入数据: {shared_data}")
        time.sleep(random.uniform(0.2, 0.8))

        # 退出区
        wrt.release()

        time.sleep(random.uniform(1, 2))


# 写者优先相关信号量
read_try = threading.Semaphore(1)  # 阻止新读者在写者等待时进入
write_count = 0
mutex_write = threading.Semaphore(1)  # 保护write_count


# 写者优先 - 读者线程
def reader_writer_priority(reader_id):
    global read_count, shared_data
    while True:
        read_try.acquire()  # 尝试读取
        mutex.acquire()
        read_count += 1
        if read_count == 1:
            wrt.acquire()
        mutex.release()
        read_try.release()

        # 读取数据
        print(f"读者{reader_id} 读取数据: {shared_data}")
        time.sleep(random.uniform(0.1, 0.5))

        mutex.acquire()
        read_count -= 1
        if read_count == 0:
            wrt.release()
        mutex.release()

        time.sleep(random.uniform(0.5, 1.5))


# 写者优先 - 写者线程
def writer_writer_priority(writer_id):
    global shared_data, write_count
    while True:
        mutex_write.acquire()
        write_count += 1
        if write_count == 1:
            read_try.acquire()  # 第一个写者阻塞新读者
        mutex_write.release()

        wrt.acquire()
        # 写入数据
        shared_data = random.randint(1, 100)
        print(f"写者{writer_id} 写入数据: {shared_data}")
        time.sleep(random.uniform(0.2, 0.8))
        wrt.release()

        mutex_write.acquire()
        write_count -= 1
        if write_count == 0:
            read_try.release()  # 最后一个写者允许新读者
        mutex_write.release()

        time.sleep(random.uniform(1, 2))


if __name__ == "__main__":
    # 测试读者优先策略
    print("=== 读者优先策略 ===")
    for i in range(3):
        threading.Thread(target=reader_priority, args=(i,), daemon=True).start()
    for i in range(2):
        threading.Thread(target=writer_priority, args=(i,), daemon=True).start()

    time.sleep(10)

    print("\n=== 写者优先策略 ===")
    # 重置变量
    read_count = 0
    write_count = 0

    # 测试写者优先策略
    for i in range(3):
        threading.Thread(target=reader_writer_priority, args=(i,), daemon=True).start()
    for i in range(2):
        threading.Thread(target=writer_writer_priority, args=(i,), daemon=True).start()

    time.sleep(10)

